// hello triangle
//
// https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/
//
// note:
// 顶点数组对象：Vertex Array Object (VAO)
// 顶点缓冲对象： Vertex Buffer Object (VBO)
// 元素缓冲对象：Element Buffer Object (EBO) 或者 索引缓冲对象：Index Buffer Object (IBO)
//
// 图形渲染管线：第一、把你的3D坐标转换为2D坐标，第二、是把2D坐标转变为实际的有颜色的像素
package main

import (
	"fmt"
	"runtime"
	"strings"

	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/glfw/v3.3/glfw"
)

func init() {
	runtime.LockOSThread()
}

func main() {
	err := glfw.Init()
	if err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(640, 480, "go-ogl", nil, nil)
	if err != nil {
		panic(err)
	}

	window.MakeContextCurrent()

	processInput(window)

	// 必须在`MakeContextCurrent` 之后调用
	err = gl.Init()
	if err != nil {
		println("gl-init err:", err)
		return
	}

	processInput(window)

	vertexes := []float64{
		-0.5, -0.5, 0.0,
		0.5, -0.5, 0.0,
		0.0, 0.5, 0.0,
	}

	var VBO uint32
	gl.GenBuffers(1, &VBO)
	gl.BindBuffer(gl.ARRAY_BUFFER, VBO)
	gl.BufferData(gl.ARRAY_BUFFER, 4*len(vertexes), gl.Ptr(vertexes), gl.STATIC_DRAW)

	vs_shader := gl.CreateShader(gl.VERTEX_SHADER)
	triangle_vs := `#version 330 core
	layout (location = 0 )in vec3 aPos;

	void main(){
		gl_Position=vec4(aPos.x,aPos.y, aPos.z, 1.0)
	}\x00
	`
	csources, free := gl.Strs(triangle_vs)
	gl.ShaderSource(vs_shader, 1, csources, nil)
	free()
	gl.CompileShader(vs_shader)

	var status int32
	gl.GetShaderiv(vs_shader, gl.COMPILE_STATUS, &status)
	if status == gl.FALSE {
		var logLength int32
		gl.GetShaderiv(vs_shader, gl.INFO_LOG_LENGTH, &logLength)
		log := strings.Repeat("\x00", int(logLength+1))
		gl.GetShaderInfoLog(vs_shader, logLength, nil, gl.Str(log))
		panic(fmt.Errorf("failed to compile %v: %v", csources, log))
	}

	for !window.ShouldClose() {
		gl.ClearColor(0.5, 0.3, 0.3, 1)
		gl.Clear(gl.COLOR_BUFFER_BIT)
		// Do OpenGL stuff.
		window.SwapBuffers()
		glfw.PollEvents()
	}
	// __main()
}
func processInput(window *glfw.Window) {
	window.GetKey(glfw.KeyEscape)
	window.SetKeyCallback(func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
		if key == glfw.KeyEscape && action == glfw.Press {
			println(">> escape press...", scancode)
			window.SetShouldClose(true)
		}
		if key == glfw.KeyA && action == glfw.Release {
			println(">> a press...", scancode)
		}
	})
}
